#!/bin/bash

# Temporary file path.
IMAGE_DIR=$1

IMAGE_ID=${IMAGE_DIR##*/}
IMAGE_FILE=${IMAGE_DIR}/bios.bin
BIOS_MTD_DEVICE=

CURRENT_VERSION=
UPDATE_VERSION=

# Get the current BIOS version.
get_bios_version()
{
    OBJ='xyz.openbmc_project.Software.BMC.Updater'
    INTERFACE='xyz.openbmc_project.Software.Version'
    PROPERTY='Version'

    OBJ_PATH="/xyz/openbmc_project/software/${IMAGE_ID}"
    CMD="busctl get-property  $OBJ $OBJ_PATH $INTERFACE $PROPERTY"
    str=$($CMD)
    str=${str#*\"}
    UPDATE_VERSION=${str%%\"*}

    OBJ_PATH="/xyz/openbmc_project/software/bios_active"
    CMD="busctl get-property  $OBJ $OBJ_PATH $INTERFACE $PROPERTY"
    str=$($CMD)
    str=${str#*\"}
    CURRENT_VERSION=${str%%\"*}

    return 0
}

# Generate redfish logs.
generate_redfish_log()
{
    if [ ! -d "/var/log" ]; then
        mkdir -p /var/log
    fi

    OPENBMC_TAG="OpenBMC.0.1.$1"
    PARA=""
    shift
    while [ $# -ne 0 ]; do
        PARA=$PARA",$1"
        shift
    done
    logger -p local7.info "${OPENBMC_TAG}${PARA}"
}

# Delete the path after the update failed.
delete_error_image()
{
    ERROR_PATH=/xyz/openbmc_project/software/${IMAGE_ID}

    busctl call xyz.openbmc_project.Software.BMC.Updater \
        ${ERROR_PATH} xyz.openbmc_project.Object.Delete Delete

}

# Check the command status.
check_cmd_state()
{
    if [ $? -ne 0 ]; then
        echo "$1 Failed..."
        generate_redfish_log "FirmwareUpdateFailed" "$CURRENT_VERSION" \
            "$UPDATE_VERSION" "$1 Failed..."

        delete_error_image
        exit 1
    fi
}

# Check the MTD device.
check_mtd_device()
{
    all_mtd_device=`ls /sys/class/mtd/mtd*/name`
    for mtd in $all_mtd_device ; do
        d=`cat $mtd`
        if [[ $d == $1 ]]; then
            tmp=${mtd%/*}
            BIOS_MTD_DEVICE=/dev/${tmp##*/}
            return 0
        fi
    done
    echo "Not find $1 mtd device"
    return 1
}

setup_spi_drive()
{
    if [ $1 = "bind" ]; then
        if [ -e ${SPI_PATH}/$SPI_DEV ]; then
            echo  "${SPI_DEV}" > ${SPI_PATH}/unbind
        fi

        sleep 0.5
        echo  "${SPI_DEV}" > ${SPI_PATH}/bind

        check_mtd_device "pnor"
        return $?
    elif [[ $1 = "unbind" && -e ${SPI_PATH}/$SPI_DEV ]]; then
        echo  "${SPI_DEV}" > ${SPI_PATH}/unbind
        sleep 0.5
    fi

    return 0;
}

#Set GPIO to make CPLD enable or disable spi channel of BIOS
setup_bios_update()
{
    BIOS_UPDATE_ENABLE="CPU1_SPI_SELECT"
    echo "Setup BMC Update BIOS: Flash to $1"

    data=`gpioutil get $BIOS_UPDATE_ENABLE`
    data=${data#*: }
    if [[ "$1" = "cpu" && "$data" = "1" ]]; then
        gpioutil set $BIOS_UPDATE_ENABLE 0
    elif [[ "$1" = "bmc" && "$data" = "0" ]]; then
        gpioutil set $BIOS_UPDATE_ENABLE 1
    fi

    sleep 0.5

    return 0

}

# Set bios update dbus progress interface
# $1=Progress
set_dbus_progress_info()
{
    OBJ='xyz.openbmc_project.Software.BMC.Updater'
    OBJ_PATH="/xyz/openbmc_project/software/${IMAGE_ID}"
    INTERFACE='xyz.openbmc_project.Software.ActivationProgress'
    PROPERTY='Progress'

    busctl set-property  $OBJ $OBJ_PATH $INTERFACE $PROPERTY y $1
    check_cmd_state "Set FW:$ID progress=$1% progress to dbus interface"

    return 0
}

# Flash the new firmware into the BIOS
start_flash_BIOS()
{
    echo "Flashing bios image to $BIOS_MTD_DEVICE..."
    if [ ! -e $BIOS_MTD_DEVICE ]; then
        generate_redfish_log "FirmwareUpdateFailed" "$CURRENT_VERSION" \
        "$UPDATE_VERSION" "flashcp updated Failed : BIOS mtd device \
        $BIOS_MTD_DEVICE does not exist"

        return 1
    fi

    # Added progress monitoring function
    echo "wait" > /tmp/bios_flash_progress
    sh /usr/local/progress_monitoring.sh $IMAGE_DIR $1 $2&

    # sleep 2
    flashcp -v $IMAGE_FILE $BIOS_MTD_DEVICE > /tmp/bios_flash_progress
    if [ $? -eq 0 ]; then
        echo "bios flashcp updated successfully..."
    else
        echo "bios flashcp updated Failed..."
        echo "Unbind spi driver"
        setup_spi_drive "unbind"
        generate_redfish_log "FirmwareUpdateFailed" "$CURRENT_VERSION" \
            "$UPDATE_VERSION" "flashcp updated Failed..."

        sleep 0.5

        return 1
    fi
    echo "end" > /tmp/bios_flash_progress

    # Wait for the subscript progress_monitoring.sh to exit
    wait

    return 0
}

#############################################################
#
#MIAN
#
#############################################################
echo "Bios upgrade started at $(date)"

get_bios_version

# Check the file to be burned
set_dbus_progress_info 21
if [ ! -e "$IMAGE_FILE" ]; then
    echo "Bios image $IMAGE_FILE doesn't exist"
    generate_redfish_log "FirmwareUpdateFailed" "$CURRENT_VERSION" \
        "$UPDATE_VERSION" "Uploading the wrong firmware,BIOS image \
        $IMAGE_FILE doesn't exist"

    exit 1
fi

# Flip GPIO to access SPI flash used by host.
# Enable Update,BIOS to BMC
setup_bios_update "bmc"
set_dbus_progress_info 22

# Bind spi driver to access flash
setup_spi_drive "bind"
check_cmd_state "Bind BIOS SPI Flash "
set_dbus_progress_info 25

# Flashcp image to device.
start_flash_BIOS 30 100

echo "Start Unbind bmc spi controller driver"
setup_spi_drive "unbind"

# Flip GPIO back for host to access SPI flash
# Disable Update,BIOS to CPU
setup_bios_update "cpu"

generate_redfish_log "FirmwareUpdateCompleted" "$CURRENT_VERSION" "$UPDATE_VERSION"

echo "Bios eeprom service update finish"
